package com.katesoft.scale4j.rttp.subscription;

import com.katesoft.scale4j.common.annotation.ValueObject;
import com.katesoft.scale4j.common.model.IPrettyPrintableObject;
import com.katesoft.scale4j.persistent.model.unified.AbstractPersistentEntity;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.springframework.beans.factory.annotation.Required;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;

/**
 * this class allows to subscribe for domain entities events(inserts, updates).
 * <p/>
 * jvmcluster-rttp will provided multi-threaded distributed execution of business processes.
 * 
 * @author kate2007
 */
@ValueObject
public class CloudSubscription<T extends AbstractPersistentEntity> implements Serializable,
         IPrettyPrintableObject, ICloudSubscription<T> {
   private static final long serialVersionUID = -6860939101796161574L;

   private Class<T> subscriptionClass;
   private IUnaryPredicate<T> predicate;
   private Collection<IBusinessProcess<T>> processes;

   /**
    * specify domain entity class that should be tracked. this field is required.
    * 
    * @param subscriptionClass
    *           domain class
    */
   @Required
   public void setSubscriptionClass(Class<T> subscriptionClass) {
      this.subscriptionClass = subscriptionClass;
   }

   /**
    * specify business predicate to be evaluated. this field is required.
    * 
    * @param predicate
    *           business predicate
    */
   @Required
   public void setPredicate(IUnaryPredicate<T> predicate) {
      this.predicate = predicate;
   }

   /**
    * specify business processes to be executed in case of successful predicate evaluation.
    * <p/>
    * each of business processed will be wrapped with distributed(load balanced) multi threaded
    * execution.
    * 
    * @param processes
    *           collection of business processes.
    */
   @Required
   public void setProcesses(Collection<IBusinessProcess<T>> processes) {
      this.processes = processes;
   }

   @Override
   public Class<T> getSubscriptionClass() {
      return subscriptionClass;
   }

   @Override
   public IUnaryPredicate<T> getPredicate() {
      return predicate;
   }

   @Override
   public Collection<IBusinessProcess<T>> getProcesses() {
      return processes;
   }

   @Override
   public String reflectionToString() {
      return ReflectionToStringBuilder.reflectionToString(this);
   }

   public static <T extends AbstractPersistentEntity> ICloudSubscription<T> newInstance(
            IUnaryPredicate<T> predicate, IBusinessProcess<T> process, Class<T> clazz) {
      CloudSubscription<T> subscription = new CloudSubscription<T>();

      subscription.setProcesses(Collections.singleton(process));
      subscription.setPredicate(predicate);
      subscription.setSubscriptionClass(clazz);

      return subscription;
   }
}
